package other

import "errors"

type MyStructOption func(myStruct *MyStruct)
type MyStructOptionErr func(myStruct *MyStruct) error

type MyStruct struct {
	// 有两部分, 1.必须用户输入 2.可选
	// 必传
	id   uint64
	name string

	// 可选
	address string
	// ...

	field1 int
	field2 int
}

func WithField1And2(field1 int, field2 int) MyStructOption {
	return func(myStruct *MyStruct) {
		myStruct.field1 = field1
		myStruct.field2 = field2
	}
}

func WithAddress(address string) MyStructOption {
	return func(myStruct *MyStruct) {
		myStruct.address = address
	}
}

func WithField1And2V1(field1 int, field2 int) MyStructOptionErr {
	return func(myStruct *MyStruct) error {
		myStruct.field1 = field1
		myStruct.field2 = field2
		return nil
	}
}

func WithAddressV1(address string) MyStructOptionErr {
	return func(myStruct *MyStruct) error {
		if address == "" {
			return errors.New("地址不能为空")
		}
		myStruct.address = address
		return nil
	}
}

func WithAddressV2(address string) MyStructOption {
	return func(myStruct *MyStruct) {
		if address == "" {
			panic(errors.New("地址不能为空"))
		}
		myStruct.address = address
	}
}

// 参数包含用户所有必须传入的字段
func NewMyStruct(id uint64, name string, opts ...MyStructOption) *MyStruct {
	// 必传部分
	res := &MyStruct{
		id:   id,
		name: name,
	}
	for _, opt := range opts {
		opt(res)
	}
	return res
}

// 参数包含用户所有必须传入的字段
func NewMyStructV1(id uint64, name string, opts ...MyStructOptionErr) (*MyStruct, error) {
	// 必传部分
	res := &MyStruct{
		id:   id,
		name: name,
	}
	for _, opt := range opts {
		if err := opt(res); err != nil {
			return nil, err
		}
	}
	return res, nil
}
